package com.jintian.smart.kernel.flowable.engine;

import com.jintian.smart.kernel.common.util.StringUtil;
import com.jintian.smart.kernel.core.auth.IOperator;
import com.jintian.smart.kernel.core.auth.IOperatorProvider;
import com.jintian.smart.kernel.core.auth.IOrgUnitQuery;
import com.jintian.smart.kernel.core.dto.OrgUnit;
import com.jintian.smart.kernel.core.flow.*;
import com.jintian.smart.kernel.core.orm.IBizTable;
import com.jintian.smart.kernel.core.orm.IBizTableLoader;
import com.jintian.smart.kernel.flowable.api.PermissionService;
import com.jintian.smart.kernel.flowable.component.ProcessContextProvider;
import com.jintian.smart.kernel.flowable.context.DefaultProcessContext;
import com.jintian.smart.kernel.flowable.domain.model.FlowImpl;
import com.jintian.smart.kernel.flowable.flowable.cmd.AddHistoricVariableCmd;
import com.jintian.smart.kernel.flowable.flowable.cmd.FetchTaskIdentityLinkEntityCmd;
import com.jintian.smart.kernel.module.Model;
import com.jintian.smart.kernel.orm.context.BizTableContextImpl;
import com.jintian.smart.kernel.orm.impl.BizTableImpl;
import lombok.extern.slf4j.Slf4j;
import org.beetl.sql.annotation.entity.Table;
import org.beetl.sql.clazz.kit.BeanKit;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLinkInfo;
import org.flowable.identitylink.api.IdentityLinkType;
import org.flowable.identitylink.service.impl.persistence.entity.IdentityLinkEntity;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

@Slf4j
public class BaseProcessService extends DelegateProcessEngine implements ApplicationContextAware {
    protected static final TaskCheckEnum[] DEFAULT_TASK_CHECK = new TaskCheckEnum[]{TaskCheckEnum.Active, TaskCheckEnum.OwnerOrAssignee};

    public enum TaskCheckEnum {
        Active("任务挂起中"), OwnerOrAssignee("不是您的任务");
        private final String desc;

        private TaskCheckEnum(String desc) {
            this.desc = desc;
        }

        public String getDesc() {
            return desc;
        }
    }

    @Autowired
    private IActionInvoker flowActionInvoker;

    @Autowired
    protected IOperatorProvider operatorProvider;

    @Autowired
    protected IOrgUnitQuery operatorQuery;

    @Autowired
    protected ProcessContextProvider processContextProvider;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    protected IBizTableLoader bizTableLoader;

    @Autowired
    protected FlowLoader flowLoader;

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    protected ApplicationContext getApplicationContext() {
        return this.applicationContext;
    }

    protected PermissionService permissionService() {
        return this.permissionService;
    }

    protected IProcessContext<List<TaskInfo>> currentProcessContext() {
        return this.processContextProvider.currentProcessContext();
    }

    protected List<TaskInfo> activeTasks(String processInstanceId) {
        return this.activeTasks(processInstanceId, null);
    }

    @SuppressWarnings("unchecked")
    protected List<TaskInfo> activeTasksIncludeIdentityLinks(String processInstanceId) {
        TaskQuery query = this.taskQuery().processInstanceId(processInstanceId).includeIdentityLinks().active();
        List<? extends TaskInfo> ret = query.list();
        return (List<TaskInfo>) ret;
    }

    @SuppressWarnings("unchecked")
    protected List<TaskInfo> activeTasks(String processInstanceId, String executor) {
        TaskQuery query = this.taskQuery().processInstanceId(processInstanceId).active();
        if (executor != null) {
            query = query.taskAssignee(executor);
        }
        List<? extends TaskInfo> ret = query.list();
        return (List<TaskInfo>) ret;
    }

    protected ProcessInstance getProcessInstance(String processInstanceId) {
        ProcessInstance ret = (ProcessInstance) this.executionQuery().processInstanceId(processInstanceId).onlyProcessInstanceExecutions().singleResult();
        return ret;
    }

    /**
     * 获取主角的任务
     *
     * @param processInstanceId
     * @return
     */
    protected TaskEntity getPrincipalTask(String processInstanceId, IOperator operator) {
        if (operator == null) {
            throw new IllegalArgumentException("未指定操作者");
        }
        TaskQuery query = this.taskQuery().processInstanceId(processInstanceId);
        List<Task> tasks = query.list();
        if (tasks.size() == 0) {
            throw new IllegalArgumentException("不存在活动中的流程任务");
        }
        for (Task task : tasks) {
            if (permissionService.canExecute(operator, task)) {
                return (TaskEntity) task;
            }
        }
        throw new IllegalArgumentException("没有此流程操作权限");
    }

    protected List<TaskEntity> findPrincipalTaskList(String processInstanceId, IOperator operator) {
        if (operator == null) {
            throw new IllegalArgumentException("未指定操作者");
        }
        List<TaskEntity> taskList = new ArrayList<>();
        String userId = Authentication.getAuthenticatedUserId();
        if (StringUtil.isBlank(userId)) {
            return null;
        }
        TaskQuery query = this.taskQuery().processInstanceId(processInstanceId);
        // TODO 浪潮工作流根据任务获取用户，作为代理
        List<Task> tasks = query.includeIdentityLinks().list();
        for (Task task : tasks) {
            if (permissionService.canExecute(operator, task)) {
                taskList.add((TaskEntity) task);
            }
        }
        return taskList;
    }

    protected TaskEntity loadTask(String taskId) {
        return (TaskEntity) this.taskQuery().taskId(taskId).singleResult();
    }

    protected String validTask(TaskEntity task, IOperator IOperator, TaskCheckEnum check) {
        switch (check) {
            case Active:
                if (task.isCanceled()) {
                    return "任务已取消";
                } else if (task.isSuspended()) {
                    return "任务挂起中";
                }
                return null;
            case OwnerOrAssignee:
                IOperator ckeckIOperator = FlowAction.getFlowOwner();
                if (task.getDelegationState() != null && task.getDelegationState().equals(DelegationState.PENDING)) {
                    if (task.getAssignee().equals(ckeckIOperator.getId())) {
                        return null;
                    } else {
                        return "您无权限操作委托给用户" + task.getAssignee() + "的任务";
                    }
                }
                if (this.permissionService().canExecute(ckeckIOperator, task)) {
                    return null;
                } else {
                    List<OrgUnit> orgUnitList = this.permissionService().getCanExecutor(task);
                    String message = orgUnitList.stream().map((unit) -> {
                        return unit.getKind().getDesc() + ":" + unit.getName();
                    }).collect(Collectors.joining(","));
                    return "您不在以下有效执行者范围内:" + message;
                }
            default:
                return null;
        }

    }

    protected void checkTask(TaskEntity task, IOperator IOperator, TaskCheckEnum... check) {
        Assert.isTrue(task != null, "任务已完成");
        for (TaskCheckEnum c : check) {
            String msg = validTask(task, IOperator, c);
            if (msg != null) {
                throw new FlowableException(msg);
            }
        }
    }

    protected org.flowable.bpmn.model.Process getMainProcess(String processDefinitionId) {
        return this.repositoryService().getBpmnModel(processDefinitionId).getMainProcess();
    }

    /**
     * 检查新任务的执行者
     *
     * @param task
     */
    protected void checkNewTaskExecutor(TaskEntity task) {
        if (task.getAssignee() == null && task.getOwner() == null) {
            List<IdentityLinkEntity> links = this.managementService().executeCommand(new FetchTaskIdentityLinkEntityCmd(task.getId()));
            links = links.stream().filter(e -> IdentityLinkType.CANDIDATE.equals(e.getType())).collect(Collectors.toList());
            if (links.size() == 0 && StringUtil.isAllBlank(task.getOwner(), task.getAssignee())) {
                // 如果没有候选人、且无执行人，发送给自己
                // taskService().setOwner(task.getId(),
                // currentProcessContext().getExecutorId());
                taskService().setAssignee(task.getId(), currentProcessContext().getOperatorId());
            }
        }
    }

    protected void abortTask(TaskEntity currentTask, ProcessControl processControl) throws Exception {
        String processInstanceId = currentTask.getProcessInstanceId();
        ProcessInstance processInstance = this.processInstanceQuery().processInstanceId(processInstanceId).singleResult();
        Assert.isTrue(!processInstance.isEnded(), "流程已结束");

        try (DefaultProcessContext context = (DefaultProcessContext) this.processContextProvider.createInstance(
                processInstance.getProcessDefinitionKey(), currentTask.getTaskDefinitionKey(), FlowAction.abortTask,
                processInstanceId, currentTask.getId(), processInstance.getBusinessKey(), processControl);) {
            this.beforeAction(currentTask, context, FlowAction.abort);
            BaseProcessService self = this;
            flowActionInvoker.invoke(context, new Callable<List<TaskInfo>>() {
                @Override
                public List<TaskInfo> call() throws Exception {
                    // 作废数据
                    self.innerAbortTask(currentTask, context);
                    return null;
                }
            });
        }
    }

    private void innerAbortTask(Task currentTask, DefaultProcessContext context) {
        String processInstanceId = currentTask.getProcessInstanceId();

        Map<String, Object> fixedVariables = new HashMap<>();
        String abortReason = (String) context.getVariables().get(FlowAction.VARNAME_ABORT_REASON);
        context.getVariables().entrySet().forEach(e -> {
            if (e.getKey().startsWith("abort")) {
                // 办结信息
                fixedVariables.put(AddHistoricVariableCmd.varNamePrefix + e.getKey(), e.getValue());
            } else {
                fixedVariables.put(e.getKey(), e.getValue());
            }
        });
        // 补充办结信息
        if (!fixedVariables.containsKey(AddHistoricVariableCmd.varNamePrefix + FlowAction.VARNAME_ABORT_PERSONID)) {
            fixedVariables.put(AddHistoricVariableCmd.varNamePrefix + FlowAction.VARNAME_ABORT_PERSONID, context.getOperatorId());
        }
        if (!fixedVariables.containsKey(AddHistoricVariableCmd.varNamePrefix + FlowAction.VARNAME_ABORT_PERSONNAME)) {
            fixedVariables.put(AddHistoricVariableCmd.varNamePrefix + FlowAction.VARNAME_ABORT_PERSONNAME, context.getOperatorName());
        }

        // TODO 更新业务状态 迁移到全局事件监听
        // this.managementService().executeCommand(new
        // SetProcessInstanceBusinessStatusCmd(processInstanceId, "abort"));
        // this.runtimeService().updateBusinessStatus(context.getProcessInstanceId(),
        // "abort");
        // 历史变量表act_hi_varinst 增加流程实例办结数据
        this.managementService().executeCommand(new AddHistoricVariableCmd(currentTask.getProcessInstanceId(),
                AddHistoricVariableCmd.HistoricVariable_ProcessInstance, fixedVariables));
        this.runtimeService().deleteProcessInstance(processInstanceId, abortReason);
    }

    private String getTaskFirstUserId(Task task) {
        String userId = new StringUtil().firstNonBlank(task.getAssignee(), task.getOwner());
        if (StringUtil.isBlank(userId)) {
            List<? extends IdentityLinkInfo> links = task.getIdentityLinks();
            String firstGroup = null;
            for (IdentityLinkInfo link : links) {
                if (!IdentityLinkType.CANDIDATE.equals(link.getType())) {
                    continue;
                }
                if (StringUtil.isNotBlank(link.getUserId())) {
                    userId = link.getUserId();
                    break;
                } else {
                    firstGroup = link.getGroupId();
                }
            }
            if (StringUtil.isBlank(userId) && StringUtil.isNotBlank(firstGroup)) {
                String[] args = firstGroup.split(":");
                String kind = null;
                String code = null;
                if (args.length == 1) {
                    kind = "role";
                    code = args[0];
                } else {
                    kind = args[0];
                    code = args[1];
                }
                OrgUnit group = this.operatorQuery.query(kind, code, true);
                if (group.getIncludeUsers().size() > 0) {
                    userId = group.getIncludeUsers().get(0).getId();
                }
            }
        }
        return userId;
    }

    protected String getTaskFirstUserId(String pid, FlowAction action) {
        List<Task> tasks = this.taskQuery().processInstanceId(pid).includeIdentityLinks().orderByTaskCreateTime().asc()
                .list();
        for (Task task : tasks) {
            if (action.equals(FlowAction.resume) && task.isSuspended()) {
                return getTaskFirstUserId(task);
            } else {
                return getTaskFirstUserId(task);
            }
        }
        return null;
    }

    protected List<TaskInfo> invokeAction(IProcessContext<List<TaskInfo>> context, Callable<List<TaskInfo>> callable) throws Exception {
        List<TaskInfo> taskInfoList = flowActionInvoker.invoke(context, callable);
        // 动作完成后的检查代码
        if (FlowAction.complete.equals(context.getAction())) {
            if (taskInfoList.size() == 0) {
                ((DefaultProcessContext) context).setProcessFinished(this.executionQuery().processInstanceId(context.getProcessInstanceId()).count() == 0);
            }
        } else if (FlowAction.abortTask.equals(context.getAction())) {
            if (log.isDebugEnabled()) {
                Assert.isTrue(this.executionQuery().processInstanceId(context.getProcessInstanceId()).count() == 0, "作废操作异常,活动流程实例(act_ru_execution)未删除");
            }
            ((DefaultProcessContext) context).setProcessFinished(true);
        }
        return taskInfoList;
    }

    public List<UserTask> getPrevUserTask(Task task) {
        org.flowable.bpmn.model.Process process = this.getMainProcess(task.getProcessDefinitionId());
        FlowNode currentActivity = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey());
        List<UserTask> prevUserTasks = new ArrayList<>();
        this.getPrevUserTask(currentActivity, prevUserTasks, null);
        prevUserTasks.remove(currentActivity);
        return prevUserTasks;

    }

    public void getPrevUserTask(FlowNode currentActivity, List<UserTask> userTaskList, Set<SequenceFlow> checkFlow) {
        if (checkFlow == null)
            checkFlow = new HashSet<>();
        List<FlowNode> prevOther = new ArrayList<>();
        for (SequenceFlow flow : currentActivity.getIncomingFlows()) {
            if (checkFlow.contains(flow)) {
                continue;
            }
            checkFlow.add(flow);
            FlowElement prev = flow.getSourceFlowElement();
            if (prev instanceof FlowNode) {
                if (prev instanceof UserTask) {
                    if (!userTaskList.contains(prev))
                        userTaskList.add((UserTask) prev);
                }
                prevOther.add((FlowNode) prev);
            }
        }

        for (FlowNode other : prevOther) {
            this.getPrevUserTask(other, userTaskList, checkFlow);
        }
    }

    public List<FlowNode> getNextFlowNode(Task task) {
        // https://www.codenong.com/cs105167220/
        org.flowable.bpmn.model.Process process = this.getMainProcess(task.getProcessDefinitionId());
        FlowNode currentActivity = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey());
        List<FlowNode> nextUserTasks = new ArrayList<>();
        this.getNextFlowNode(currentActivity, nextUserTasks, null);
        nextUserTasks.remove(currentActivity);
        return nextUserTasks;
    }

    // private void setSpecialGatewayList(String sourceActivityId, String
    // targetActivityId, Map<String, Set<String>> specialGatewayNodes,
    // List<String> sourceInSpecialGatewayList, List<String>
    // targetInSpecialGatewayList) {
    // for (Map.Entry<String, Set<String>> entry : specialGatewayNodes.entrySet()) {
    // if (entry.getValue().contains(sourceActivityId)) {
    // sourceInSpecialGatewayList.add(entry.getKey());
    // }
    // if (entry.getValue().contains(targetActivityId)) {
    // targetInSpecialGatewayList.add(entry.getKey());
    // }
    // }
    // }

    private void getNextFlowNode(FlowNode currentActivity, List<FlowNode> userTaskList, Set<SequenceFlow> checkFlow) {
        if (checkFlow == null)
            checkFlow = new HashSet<>();
        List<FlowNode> notUserTaskList = new ArrayList<>();
        List<ExtensionAttribute> inheritedConditions = currentActivity.getAttributes().get("conditionExpression");

        for (SequenceFlow flow : currentActivity.getOutgoingFlows()) {
            if (checkFlow.contains(flow)) {
                continue;
            }
            checkFlow.add(flow);
            FlowElement next = flow.getTargetFlowElement();
            if (next instanceof FlowNode) {
                List<ExtensionAttribute> thisCondition = new ArrayList<>();
                if (inheritedConditions != null) {
                    thisCondition.addAll(inheritedConditions);
                }
                if (StringUtil.isNotBlank(flow.getConditionExpression())) {
                    ExtensionAttribute conditionExpression = new ExtensionAttribute();
                    conditionExpression.setName("conditionExpression");
                    conditionExpression.setValue(flow.getConditionExpression());
                    thisCondition.add(conditionExpression);
                }
                if (thisCondition.size() > 0) {
                    next.getAttributes().put("conditionExpression", thisCondition);
                }
                if (next instanceof UserTask || next instanceof EndEvent) {
                    if (!userTaskList.contains(next))
                        userTaskList.add((FlowNode) next);
                } else {
                    if (!notUserTaskList.contains(next))
                        notUserTaskList.add((FlowNode) next);
                }
            }
        }

        for (FlowNode notUserTask : notUserTaskList) {
            this.getNextFlowNode(notUserTask, userTaskList, checkFlow);
        }
    }

    protected void beforeAction(Task task, DefaultProcessContext processContext, FlowAction action) throws Exception {
        ProcessControl processControl = processContext.getProcessControl();
        // 1.构建runtime
        Map<String, Object> context = new HashMap<>();
        context.putAll(processControl.getBizVariables());
        context.putAll(processControl.getTransientVariables());
        context.putAll(processControl.getVariables());

        this.buildFlowRuntimeContext(task, context);
        ProcessInstance pi = (ProcessInstance) context.get(DefaultFlowRuntime.CONTEXT_PROCESSINSTANCE);
        String bizClass = (String) pi.getProcessVariables().get(FlowAction.VARNAME_START_BIZCLASS);
        String modelName = (String) pi.getProcessVariables().get(FlowAction.VARNAME_START_MODELNAME);

        DefaultFlowRuntime flowRuntime = this.createFlowRuntime(bizClass, modelName, pi.getProcessDefinitionKey(),
                pi.getProcessDefinitionVersion(), context);
        processContext.setFlowRuntime(flowRuntime);

        // 2. 应用变量到上下文环境中，开始计算下一环节。(不建议业务规则中使用变量，直接使用表、字段容易理解)
        // 不同于queryProcessControl，这些变量会同时传递给流程引擎
        Map<String, Object> processVariables = flowRuntime.applyProcessVariablesToContext();
        for (Entry<String, Object> e : processVariables.entrySet()) {
            if (!processContext.getTransientVariables().containsKey(e.getKey())) {
                processContext.getTransientVariables().put(e.getKey(), e.getValue());
            }
        }

        // 3.检查业务规则
        List<Object> checkResult = flowRuntime.checkRule(task.getTaskDefinitionKey(), action);
        String stopMessage = flowRuntime.getStopMessage(checkResult);
        if (StringUtil.isNotBlank(stopMessage)) {
            throw new FlowableException(stopMessage);
        }

        if (flowRuntime.getBizBean() != null) {
            processContext.getTransientVariables().put(FlowAction.TRANSIENT_VARNAME_BIZBEAN, flowRuntime.getBizBean());
        }
        processContext.getTransientVariables().put(FlowAction.TRANSIENT_VARNAME_OPERATOR, processContext.getOperator());
    }

    protected void buildFlowRuntimeContext(Task task, Map<String, Object> context) {
        String activity = task.getTaskDefinitionKey();
        ProcessInstance pi = this.runtimeService().createProcessInstanceQuery().includeProcessVariables()
                .processInstanceId(task.getProcessInstanceId()).singleResult();

        if (!context.containsKey(ITaskOperation.FORMURL_PARAM_ACTIVITY)) {
            context.put(ITaskOperation.FORMURL_PARAM_ACTIVITY, activity);
        }
        if (!context.containsKey(ITaskOperation.FORMURL_PARAM_ACTIVITYLABEL)) {
            context.put(ITaskOperation.FORMURL_PARAM_ACTIVITYLABEL, task.getName());
        }
        if (!context.containsKey(ITaskOperation.FORMURL_PARAM_PROCESS)) {
            context.put(ITaskOperation.FORMURL_PARAM_PROCESS, pi.getProcessDefinitionKey());
        }

        if (!context.containsKey(ITaskOperation.FORMURL_PARAM_BUSINESS_KEY)) {
            context.put(ITaskOperation.FORMURL_PARAM_BUSINESS_KEY, pi.getBusinessKey());
        }
        if (!context.containsKey(ITaskOperation.FORMURL_PARAM_TASKID)) {
            context.put(ITaskOperation.FORMURL_PARAM_TASKID, task.getId());
        }
        if (!context.containsKey(ITaskOperation.FORMURL_PARAM_PROCESSINSTANCEID)) {
            context.put(ITaskOperation.FORMURL_PARAM_PROCESSINSTANCEID, pi.getProcessInstanceId());
        }
        context.put(FlowAction.TRANSIENT_VARNAME_OPERATOR, this.operatorProvider.currentOperator());

        context.put(DefaultFlowRuntime.CONTEXT_PROCESSINSTANCE, pi);
        context.put(DefaultFlowRuntime.CONTEXT_CURRENTTASK, task);
    }

    @SuppressWarnings("rawtypes")
    protected DefaultFlowRuntime createFlowRuntime(String bizClass, String modelName, String processKey, Integer processVersion, Map<String, Object> context) throws Exception {
        FlowImpl flow = this.flowLoader.load(modelName, processKey, processVersion);
        if (bizClass == null) {
            bizClass = flow.getBizEntity();
        }
        ClassLoader classLoader = null;
        if (modelName != null && this.getApplicationContext().getBean("model$" + modelName, Model.class) != null) {
            Model model = this.getApplicationContext().getBean("model$" + modelName, Model.class);
            classLoader = model.getClassLoader();
        } else {
            classLoader = this.getApplicationContext().getClassLoader();
        }
        Object bizBean = null;

        // 加载业务数据
        Class<?> bizBeanClass = classLoader.loadClass(bizClass);
        String idAttr = this.bizTableLoader.getPrimaryKey(bizBeanClass);
        String bizTableName = null;
        // 设置业务主表的过滤条件
        for (IBizTable table : flow.getBizTables()) {
            if (table.getEntityClass().equals(bizClass)) {
                bizTableName = table.getName();
                if (StringUtil.isBlank(table.getCondition())) {
                    ((BizTableImpl) table).setCondition(idAttr + "= #{" + ITaskOperation.FORMURL_PARAM_BUSINESS_KEY + "}");
                }
                break;
            }
        }

        Map<String, Object> loadDataVariables = new HashMap<>(context);
        loadDataVariables.put(idAttr, context.get(ITaskOperation.FORMURL_PARAM_BUSINESS_KEY));
        Map<String, List> allData = this.bizTableLoader.loadBizTable(classLoader, flow.getBizTables(), loadDataVariables);
        // 添加业务数据访问环境，用于自定义函数获取业务数据
        BizTableContextImpl bizData = new BizTableContextImpl(allData);
        context.put("bizData", bizData);
        if (bizTableName != null) {
            List list = bizData.getTable(bizTableName);
            if (list.size() != 1) {
                Table table = BeanKit.getAnnotation(bizBeanClass, Table.class);
                String name = bizBeanClass.getSimpleName();
                if (table != null && StringUtil.isNoneBlank(table.comment())) {
                    name = table.comment();
                }
                throw new FlowableException("业务数据" + name + "[" + idAttr + "=" + context.get(ITaskOperation.FORMURL_PARAM_BUSINESS_KEY) + "]记录数应等于1，实际为" + list.size());
            }
            bizBean = list.get(0);
        }

        // 业务规则
        DefaultFlowRuntime runtime = new DefaultFlowRuntime(flow, this.managementService(), context);
        runtime.setBizBean(bizBean);
        return runtime;
    }
}
